package com.lulin.mall.product.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lulin.common.constant.ProductConstant;
import com.lulin.common.dto.SkuHasStockDTO;
import com.lulin.common.dto.SkuReductionDTO;
import com.lulin.common.dto.MemberPrice;
import com.lulin.common.dto.SpuBoundsDTO;
import com.lulin.common.dto.es.SkuEsModel;
import com.lulin.common.utils.R;
import com.lulin.mall.product.entity.*;
import com.lulin.mall.product.fegin.CouponFeginService;
import com.lulin.mall.product.fegin.SearchFeginService;
import com.lulin.mall.product.fegin.WareSkuFeginService;
import com.lulin.mall.product.service.*;
import com.lulin.mall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lulin.common.utils.PageUtils;
import com.lulin.common.utils.Query;

import com.lulin.mall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    //注入spu信息介绍的业务接口
    @Autowired
    SpuInfoDescService spuInfoDescService;
    //注入spu图片业务接口
    @Autowired
    SpuImagesService spuImagesService;
    //输入spu属性值的业务接口
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    AttrService attrService;
    @Autowired
    SkuInfoService skuInfoService;
    @Autowired
    SkuImagesService skuImagesService;
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    //远程调用Coupon服务接口
    @Autowired
    CouponFeginService couponFeginService;

    @Autowired
    CategoryService categoryService;
    @Autowired
    BrandService brandService;

    //注入远程调用ware库存服务接口
    @Autowired
    WareSkuFeginService wareSkuFeginService;

    //注入远程调用Search检索服务接口
    @Autowired
    SearchFeginService searchFeginService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 保存商品的发布信息
     *
     * @param spuInfoVo
     */
    @Transactional
    @Override
    public void saveSpuInfo(SpuInfoVO spuInfoVo) {
        //1、保存spu的基本信息  pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuInfoVo, spuInfoEntity);
        //创建时间和更新时间，需要手动同步
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        //设置上架状态 为新建状态——0 上架状态[0 - 新建，1 - 上架，2 - 下架]
        spuInfoEntity.setPublishStatus(0);
        this.save(spuInfoEntity);

        //2、保存spu的详细信息  pms_spu_info_desc
        List<String> decripts = spuInfoVo.getDecript();
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuInfoEntity.getId());//商品id
        //通过“,”连接图片
        descEntity.setDecript(String.join(",", decripts));
        spuInfoDescService.save(descEntity);

        //3、保存图集信息  pms_spu_images
        List<String> images = spuInfoVo.getImages();
        //将每一个图片信息，封装到一个imagesEntity实体对象
        List<SpuImagesEntity> imagesEntityList = images.stream().map((item) -> {
            SpuImagesEntity imagesEntity = new SpuImagesEntity();
            imagesEntity.setId(spuInfoEntity.getId());
            imagesEntity.setImgUrl(item);
            return imagesEntity;
        }).collect(Collectors.toList());
        spuImagesService.saveBatch(imagesEntityList);

        //4、保存规格参数  pms_product_attr_value(属性和商品的分配)
        List<BaseAttrs> baseAttrs = spuInfoVo.getBaseAttrs();
        //对规格参数（spu属性值）进行处理
        List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map((attr) -> {
            ProductAttrValueEntity valueEntity = new ProductAttrValueEntity();
            valueEntity.setSpuId(spuInfoEntity.getId());//商品id
            valueEntity.setAttrId(attr.getAttrId());
            valueEntity.setAttrValue(attr.getAttrValues());
            valueEntity.setQuickShow(attr.getShowDesc());
            //根据属性id,查询属性信息
            AttrEntity attrEntity = attrService.getById(attr.getAttrId());
            valueEntity.setAttrName(attrEntity.getAttrName());
            return valueEntity;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValueEntities);

        //5、保存当前的spu对应的 所有sku信息
        List<Skus> skus = spuInfoVo.getSkus();
        if (skus != null && skus.size() > 0) {
            //5.1）保存sku的基本信息 pms_sku_info
            skus.forEach((item) -> {
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item, skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSaleCount(0L);
                //获取默认的图片信息，设置到对象
                List<Images> images1 = item.getImages();
                String defaultImage = "";
                for (Images images2 : images1) {
                    if (images2.getDefaultImg() == 1) {
                        //表示默认的图片
                        defaultImage = images2.getImgUrl();
                    }
                }
                skuInfoEntity.setSkuDefaultImg(defaultImage);
                skuInfoService.save(skuInfoEntity);

                //5.2）保存sku的图片信息 pms_sku_image
                List<SkuImagesEntity> skuImagesEntities = images1.stream().map(img -> {
                    SkuImagesEntity entity = new SkuImagesEntity();
                    entity.setSkuId(skuInfoEntity.getSkuId());
                    entity.setImgUrl(img.getImgUrl());
                    entity.setDefaultImg(img.getDefaultImg());
                    return entity;
                    //为空的图片不需要保存
                }).filter(img -> {
                    return img.getDefaultImg() == 1;
                }).collect(Collectors.toList());
                skuImagesService.saveBatch(skuImagesEntities);

                /**
                 * 5.3）保存满减信息、折扣，会员价; （跨系统跨库的）mall-sms
                 *   满减表：sms_full_reduction
                 *   折扣表：sms_sku_ladder
                 *   会员价表sms_member_price
                 */
                SkuReductionDTO dto = new SkuReductionDTO();
                BeanUtils.copyProperties(item, dto);
                dto.setSkuId(skuInfoEntity.getSkuId());
                //设置会员价
                if (item.getMemberPrice() != null && item.getMemberPrice().size() > 0) {
                    List<MemberPrice> list = item.getMemberPrice().stream().map(memberPrice -> {
                        MemberPrice mDto = new MemberPrice();
                        BeanUtils.copyProperties(memberPrice, mDto);
                        return mDto;
                    }).collect(Collectors.toList());
                    dto.setMemberPrice(list);
                }
                //Cannot find local variable 'skuSaleAttrValueService'
                //调用远程处理接口的方法——保存满减信息、折扣，会员价;
                R r = couponFeginService.saveFullReductionInfo(dto);
                if (r.getCode() != 0) {
                    log.error("调用Coupon服务处理满减、折扣、会员价的操作失败");
                }

                //5.4）保存sku的销售属性  pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                List<SkuSaleAttrValueEntity> saleAttrValueEntities = attrs.stream().map((sale) -> {
                    SkuSaleAttrValueEntity entity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(sale, entity);
                    entity.setSkuId(skuInfoEntity.getSkuId());
                    return entity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(saleAttrValueEntities);
            });
        }
        //6、保存spu的积分信息 ：（跨系统跨库的）mall-sms：商品spu积分设置的表：sms_spu_bounds
        Bounds bounds = spuInfoVo.getBounds();
        SpuBoundsDTO spuBoundsDTO = new SpuBoundsDTO();
        BeanUtils.copyProperties(bounds, spuBoundsDTO);
        spuBoundsDTO.setSkuId(spuInfoEntity.getId());
        R r = couponFeginService.saveSpuBounds(spuBoundsDTO);
        if (r.getCode() != 0) {
            log.error("调用Coupon服务保存积分信息的操作失败");
        }
    }

    /**
     * SPU信息查询：根据多个条件，进行分页查询
     * 1、分页查询
     * 2、分类、品牌、状态、关键字查询等
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPageByConditon(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();

        //设置对应的条件
        //1、关键词查询
        String key = (String) params.get("key");
        //如果不等于空
        if (!StringUtils.isEmpty(key)) {
            //添加关键字查询
            wrapper.and((w) -> {
                w.eq("id", key)
                        .or().like("spu_name", key)
                        .or().like("spu_description", key);
            });
        }

        //2、上架状态(publish_status)  上架状态[0 - 新建，1 - 上架，2 - 下架]
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            wrapper.eq("publish_status", status);
        }

        //catalogIds
        String catalogId = (String) params.get("catelogId");
        //catelogId是数字，有可能传来默认值 0，也不等于0
        if (!StringUtils.isEmpty(catalogId) && !"0".equalsIgnoreCase(catalogId)) {
            wrapper.eq("catalog_id", catalogId);
        }
        //brandId
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
            wrapper.eq("brand_id", brandId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params), wrapper);

        //根据条件查询到的分页信息，查询对应的类别和品牌的名称
        List<SpuInfoVO> list = page.getRecords().stream().map(spu -> {
            //类目
            Long catalogId1 = spu.getCatalogId();
            CategoryEntity categoryEntity = categoryService.getById(catalogId1);
            //品牌
            Long brandId1 = spu.getBrandId();
            BrandEntity brandEntity = brandService.getById(brandId1);

            //创建SpuInfoVO，设置类目名称、品牌名称
            SpuInfoVO spuVo = new SpuInfoVO();
            BeanUtils.copyProperties(spu, spuVo);
            spuVo.setCatalogName(categoryEntity.getName());
            spuVo.setBrandName(brandEntity.getName());

            return spuVo;
        }).collect(Collectors.toList());

        //创建IPage分页对象，并设置需要返回的SpuInfoVO对象的分页信息
        IPage<SpuInfoVO> iPage = new Page<>();
        iPage.setRecords(list);
        iPage.setPages(page.getPages());
        iPage.setCurrent(page.getCurrent());
        iPage.setSize(page.getSize());
        iPage.setTotal(page.getTotal());

        return new PageUtils(iPage);
    }

    /**
     * 实现商品的上架、商品数据保存es中
     * <p>
     * 1.根据SpuId，查询出相关的信息，封装到对应的对象中；
     * 2.将封装的数据存储到ElasticSearch中——> 调用mall-search的远程接口
     * 3.更新SpuId对应的状态为上架
     *
     * @param spuId 商品spuId
     */
    @Transactional //我觉得要加事务处理
    @Override
    public void spuUp(Long spuId) {
        // 1.根据spuId查询相关的信息 封装到SkuESModel对象中
        ArrayList<SkuEsModel> skuEs = new ArrayList<>();
        //1.1）根据spuId,找到对应的sku信息
        List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);

        //根据spuId，查询到对应的规格参数信息
        List<SkuEsModel.Attrs> attrsModel = getAttrsModel(spuId);

        // 根据所有的skuId,获取对应的库存信息---》远程调用
        List<Long> skuIds = skus.stream().map(sku -> {
            return sku.getSkuId();
        }).collect(Collectors.toList());
        Map<Long, Boolean> skusHasStockMap = getSkusHasStock(skuIds);

        //2、远程调用mall-search的服务，保存商品信息到es中
        List<SkuEsModel> skuEsModels = skus.stream().map(item -> {
            SkuEsModel model = new SkuEsModel();
            BeanUtils.copyProperties(item, model);
            model.setSubTitle(item.getSkuTitle());
            model.setSkuPrice(item.getPrice());
            //设置默认的sku图片
            model.setSkuImg(item.getSkuDefaultImg());
            //hasStock：是否有库存——>远程调用 库存系统查询——
            //一次远程调用，获取索引的skuId对应的库存信息，不可以能有几个sku调用几次（因此，在循环外）
            if (skusHasStockMap == null) {
                model.setHasStock(true);
            } else {
                model.setHasStock(skusHasStockMap.get(item.getSkuId()));
            }

            //hotScore：热点分数 ——>刚上架，没有热度——>默认给O
            model.setHotScore(0L);

            //2.1）品牌和类别的名称
            BrandEntity brandEntity = brandService.getById(item.getBrandId());
            CategoryEntity categoryEntity = categoryService.getById(item.getCatalogId());
            model.setBrandName(brandEntity.getName());
            //2.2）品牌logo地址
            model.setBrandImg(brandEntity.getLogo());
            model.setCatalogName(categoryEntity.getName());

            //设置对应的规格参数
            model.setAttrs(attrsModel);

            return model;
        }).collect(Collectors.toList());

        // 将SkuESModel中的数据存储到ES中
        R r = searchFeginService.productStatusUp(skuEsModels);
        //3、更新spuId状态
        // 根据对应的状态，更新商品的状态
        log.info("----->ES操作完成：{}", r.getCode());//11001

        if (r.getCode() == 0) {
            // 远程调用成功——>更新商品的状态为 上架
            baseMapper.updateSpuStatusUp(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        } else {
            // 远程调用失败
        }
    }

    /**
     * 根据spuIds，查询出相关的spu信息
     *
     * @param spuIds spuid集合
     */
    @Override
    public List<OrderItemSpuInfoVO> getOrderItemSpuInfoBySpuId(Long[] spuIds) {
        ArrayList<OrderItemSpuInfoVO> list = new ArrayList<>();
        for (Long spuId : spuIds) {
            OrderItemSpuInfoVO vo = new OrderItemSpuInfoVO();
            SpuInfoEntity spuInfoEntity = this.getById(spuId);
            vo.setId(spuId);
            vo.setSpuName(spuInfoEntity.getSpuName());
            vo.setBrandId(spuInfoEntity.getBrandId());
            vo.setCatalogId(spuInfoEntity.getCatalogId());
            //根据品牌编号，查询品牌信息
            BrandEntity brandEntity = brandService.getById(spuInfoEntity.getBrandId());
            vo.setBrandName(brandEntity.getName());
            CategoryEntity categoryEntity = categoryService.getById(spuInfoEntity.getCatalogId());
            vo.setCatalogName(categoryEntity.getName());
            //获取spu的图片
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(spuId);
            vo.setImg(spuInfoDescEntity.getDecript());
            list.add(vo);
        }
        return list;
    }

    /**
     * 根据skuIds,获取对应的库存状态
     *
     * @param skuIds
     * @return
     */
    private Map<Long, Boolean> getSkusHasStock(List<Long> skuIds) {
        List<SkuHasStockDTO> skusHasStock = null;
        if (skuIds == null && skuIds.size() == 0) {
            return null;
        }
        try {
            //调用远程接口，根据skuIds,获取对应的库存状态
            skusHasStock = wareSkuFeginService.getSkusHasStock(skuIds);
            //收集，转为map集合
            //Map<Long, Boolean> map = skusHasStock.stream().collect(Collectors.toMap(item->item.getSkuId(),item->item.getHasStock()));
            Map<Long, Boolean> map = skusHasStock.stream()
                    .collect(Collectors.toMap(SkuHasStockDTO::getSkuId, SkuHasStockDTO::getHasStock));
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据spuId，查询到对应的规格参数信息
     *
     * @param spuId 商品spuId
     * @return
     */
    private List<SkuEsModel.Attrs> getAttrsModel(Long spuId) {
        //1）pms_product_attr_value：spu相关的所有规格参数
        List<ProductAttrValueEntity> baseAttrs = productAttrValueService.getBaseAttrsBySpuId(spuId);
        //2）pms_attr：search_type 绝对了——是否需要检索 [0-不需要，1-需要]
        //拿到所有的attrId
        List<Long> attrIds = baseAttrs.stream().map(item -> {
            return item.getAttrId();
        }).collect(Collectors.toList());
        //通过属性id，查询可以检索的属性编号
        List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds);
        //baseAttrs中，根据可以检索的数据过滤
        List<SkuEsModel.Attrs> attrsModel = baseAttrs.stream()
                .filter(item -> {
                    //过滤条件
                    return searchAttrIds.contains(item.getAttrId());
                }).map(item -> {
                    SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
                    BeanUtils.copyProperties(item, attr);
                    return attr;
                }).collect(Collectors.toList());
        return attrsModel;
    }
}
